#pragma once
#include "Request.h"
#include <deque>
#include <Windows.h>
#include <algorithm>

class RequestQueue
{
public:
    RequestQueue()
    {
        InitializeCriticalSection(&cs_p);
        InitializeCriticalSection(&cs_g);
        hEvent = CreateEvent(0,1,0,L"Event");
    }
    ~RequestQueue()
    {
        CloseHandle(hEvent);
        DeleteCriticalSection(&cs_p);
        DeleteCriticalSection(&cs_g);

        std::for_each(queue.begin(),queue.end(),[](Request* p)
        {
            delete p;
        });
        queue.clear();
    }

public:
    Request* getRequest()
    {
        EnterCriticalSection(&cs_g);

        while(queue.empty())
        {
            WaitForSingleObject(hEvent, INFINITE);
            ResetEvent(hEvent);
        }

        Request* r = queue.front();
        queue.pop_front();

        LeaveCriticalSection(&cs_g);

        return r;
    }

    void putRequest(Request* request)
    {
        EnterCriticalSection(&cs_p);
        
        queue.push_front(request);
        SetEvent(hEvent);

        LeaveCriticalSection(&cs_p);
    }

private:
    std::deque<Request*> queue;
    CRITICAL_SECTION cs_g;
    CRITICAL_SECTION cs_p;
    HANDLE hEvent;
};